Active Record
=============

Même si Yii DAO peut gérer n'importe quelle tache relative à la base de données,
il est fort probable qu'une grande partie du temps de développement soit consacré
à l'écriture de requêtes SQL pour faire des opérations CRUD (create, read, update and delete)
courantes. De plus il est difficile de maintenir un code quand celui est parsemé
de requêtes SQL. Active Record est là pour régler ces problèmes.

Active Record (AR) est une technique très utilisée de Object-Relational Mapping (ORM).
Chaque classe AR représente une table dans la base, dont les attributs représente une propriété
de cette classe AR, et une instance AR représente une ligne de cette table. Les opérations couramment
utilisées sont implémentées dans des méthodes de cette classe. Ainsi il est possible d'accéder
aux données d'une manière orientée objet. Par exemple, il est possible d'utiliser le code
suivant pour insérer une nouvelle ligne dans la table `tbl_post`:

~~~
[php]
$post=new Post;
$post->title='post de test';
$post->content='contenu du post de test';
$post->save();
~~~

Nous allons maintenant voir comment configurer AR et comment l'utiliser pour
effectuer des opérations CRUD. Nous verrons dans la prochaine section comment
utiliser AR pour régler les cas de clés étrangères entre tables. Pour simplifier
les choses, la table suivante sera utilisée. Attention, si vous utilisez une base
MySQL, il faut remplacer `AUTOINCREMENT` par `AUTO_INCREMENT` dans le code SQL suivant.

~~~
[sql]
CREATE TABLE tbl_post (
	id INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT,
	title VARCHAR(128) NOT NULL,
	content TEXT NOT NULL,
	create_time INTEGER NOT NULL
);
~~~

> Note: AR n'est pas fait pour régler tous les problèmes liés aux tâches touchant
à la base. AR convient le mieux pour modéliser des tables en PHP et pour effectuer
des requêtes n'impliquant pas de code SQL complexe. Yii DAO est préférable dans ces
cas de requêtes SQL complexes.


Etablir une connexion à la base de données
------------------------------------------

AR à besoin d'une connexion à une BD pour effectuer les tâches relatives à la base.
Par défaut, l'application component `db` sera utilisé pour récupérer l'instance
[CDbConnection] qui servira pour la connexion à la base. Voici un exemple de configuration:

~~~
[php]
return array(
	'components'=>array(
		'db'=>array(
			'class'=>'system.db.CDbConnection',
			'connectionString'=>'sqlite:path/to/dbfile',
			// turn on schema caching to improve performance
			// 'schemaCachingDuration'=>3600,
		),
	),
);
~~~

> Tip: Comme Active Record dépend des metadata décrivant les tables pour
connaître les informations d'une colonne, cela prend du temps lors
de la lecture des metadata et de leur analyse. S'il est peu probable que
le schéma de votre base change, il est conseillé d'activer le cache sur le
schéma en fixant la propriété [CDbConnection::schemaCachingDuration] à
une valeur supérieure à 0.

Le support pour AR est limité par le SGBD. Actuellement, seulement les SGBD suivants
le supportent:

   - [MySQL 4.1 ou plus](http://www.mysql.com)
   - [PostgreSQL 7.3 or later](http://www.postgres.com)
   - [SQLite 2 et 3](http://www.sqlite.org)
   - [Microsoft SQL Server 2000 ou plus](http://www.microsoft.com/sqlserver/)
   - [Oracle](http://www.oracle.com)

> Note: Le support de Microsoft SQL Server est disponible depuis la version 1.0.4;
> et le support pour Oracle est disponible depuis la version 1.0.5.

Si vous voulez utiliser une application component autre que `db`, ou si vous
voulez travailler sur plusieurs bases avec AR, vous pouvez surcharger [CActiveRecord::getDbConnection()].
La classe [CActiveRecord] est la classe de base pour toutes les classes AR.

> Tip: Il existe 2 moyens de gérer plusieurs BD avec AR. Si les schémas des bases
sont différents, il est possible de créer différentes classes AR de base avec différentes
implémentations de [getDbConnection()|CActiveRecord::getDbConnection]. Dans le cas contraire,
il est préférable de changer dynamiquement la variable statique [CActiveRecord::db].

Définition d'une classe AR
--------------------------

Pour accéder à une table en base, il faut tout d'abord définir une classe AR en héritant
de [CActiveRecord]. Chaque classe AR représente une seule table, et une instance AR représente
une ligne dans cette table. L'exemple suivant montre le code minimum requis pour la classe AR représentant
la table `tbl_post`.

~~~
[php]
class Post extends CActiveRecord
{
	public static function model($className=__CLASS__)
	{
		return parent::model($className);
	}

	public function tableName()
	{
		return 'tbl_post';
	}
}
~~~

> Tip: Comme les classes AR sont souvent référencées à de nombreux endroits, il est
> possible d'importer tout le répertoire contenant les classes AR, plutôt que de les
> inclure une par une. Par exemple, si tous vos fichiers de classes AR sont dans
> `protected/models`, il est possible de configurer l'application comme suit:
> ~~~
> [php]
> return array(
> 	'import'=>array(
> 		'application.models.*',
> 	),
> );
> ~~~

Par défaut, le nom de la classe AR est le même que celui de la table en base.
Il est possible de surcharger la méthode [tableName()|CActiveRecord::tableName] si
ceux-ci sont différents. La méthode [model()|CActiveRecord::model] est déclarée dans
chaque classe AR (explication peu après).

> Info: Pour utiliser les [préfixes de table](/doc/guide/database.dao#using-table-prefix)
> introduits dans la version 1.1.0, la méthode [tableName()|CActiveRecord::tableName]
> pour une classe AR peut être surchargée comme suit,
> ~~~
> [php]
> public function tableName()
> {
>     return '{{post}}';
> }
> ~~~
> Ainsi, à la place de retourner le nom de la table complète, le nom de la table
> sans le préfixe et entre doubles accolades est renvoyé.

Les valeurs en colonne d'une ligne de table sont accessibles en tant que propriétés
de l'instance AR correspondante. Par exemple, le code suivant écrit dans la colonne (attribut)
`title`:

~~~
[php]
$post=new Post;
$post->title='un post de test';
~~~

Bien que la propriété `title` ne soit jamais déclarée explicitement dans la classe `Post`,
il est tout de même possible d'y accéder dans le code précédent. Cela s'explique car `title`
est une colonne dans la table `tbl_post`, et que CActiveRecord la rend accessible en tant que
propriété grâce aux méthodes PHP `__get()`. Une exception sera levée si un accès est tenté sur
une colonne inexistante.

> Info: Dans ce guide, tous les noms des tables et des colonnes sont en minuscules.
La raison étant que les SGBD ont différentes manières de gérer la casse.
Par exemple, PostgreSQL est par défaut insensible à la casse pour les noms des colonnes,
et il faut mettre des guillemets dans les conditions pour les colonnes contenant différentes
casses. L'utilisation des minuscules permet d'éliminer ce problème.

AR dépend de la définition correcte des clés primaires sur les tables. Si une table n'a pas
de clé primaire, il est nécessaire que la classe AR correspondante spécifie quelle(s) colonne(s)
doit(vent) être la clé primaire en surchargeant la méthode `primaryKey()`,

~~~
[php]
public function primaryKey()
{
	return 'id';
	// Pour les clés primaires composites, retourne un tableau, par exemple:
	// return array('pk1', 'pk2');
}
~~~


Création des enregistrements
----------------------------

Pour insérer une nouvelle ligne dans une table, une instance de la classe AR
correspondante est créée, les propriétés sont écrites, et la méthode [save()|CActiveRecord::save]
est appelée.

~~~
[php]
$post=new Post;
$post->title='post de test';
$post->content='contenu du post de test';
$post->create_time=time();
$post->save();
~~~

Si la clé primaire de la table est en auto incrément, après l'insertion,
l'instance AR contiendra la clé primaire mise à jour. Dans l'exemple ci-dessus,
la propriété `id` sera égale à la valeur de la clé primaire du nouveau post inséré, même
si elle n'est jamais changée implicitement.

Si une colonne a été définie avec une valeur statique par défaut dans le schéma de la table,
la propriété correspondante dans l'instance AR aura automatiquement cette valeur suite à
la création de cette instance. Une façon de changer cette valeur par défaut est de déclarer
explicitement la propriété dans la classe AR:

~~~
[php]
class Post extends CActiveRecord
{
	public $title='veuillez entrer un titre';
	......
}

$post=new Post;
echo $post->title;  // cela afficherait: veuillez entrer un titre
~~~

A partir de la version 1.0.2, une valeur de type [CDbExpression] peut être
assignée à un attribut avant que l'enregistrement soit enregistré (en insertion ou
mise à jour) dans la base.
Par exemple, pour sauvegarder le timestamp retourné par la fonction MySQL `NOW()`, il
est possible d'utiliser le code suivant:

~~~
[php]
$post=new Post;
$post->create_time=new CDbExpression('NOW()');
// $post->create_time='NOW()'; ne fonctionnera pas car
// 'NOW()' sera traité comme une chaîne de caractères
$post->save();
~~~

> Tip: bien que AR permette des opérations sans avoir à écrire de requêtes SQL,
il est intéressant de savoir quelles requêtes SQL sont exécutées par AR.
Pour cela, il est possible d'activer la [fonctionnalité de log](/doc/guide/topics.logging)
de Yii. Par exemple, en activant [CWebLogRoute] dans la configuration de l'application,
les requêtes SQL seront affichées à la fin de chaque page web.
Depuis la version 1.0.5, il est possible de mettre [CDbConnection::enableParamLogging] à true
dans la configuration de l'application pour que les valeurs en paramètres liées aux requêtes SQL
apparaissent aussi dans le journal des logs.


Lecture des enregistrements
---------------------------

Pour lire des données d'une table, on appelle une des méthodes `find` comme suit:

~~~
[php]
// trouve la première ligne satisfaisant la condition
$post=Post::model()->find($condition,$params);
// trouve la ligne avec la clé primaire spécifiée
$post=Post::model()->findByPk($postID,$condition,$params);
// trouve la ligne avec les valeurs d'attributs spécifiées
$post=Post::model()->findByAttributes($attributes,$condition,$params);
// trouve la première ligne en utilisant la requête SQL spécifiée
$post=Post::model()->findBySql($sql,$params);
~~~

Ci-dessus, l'appel de la méthode `find` est effectué au travers de `Post::model()`.
Ne pas oublier que la méthode statique `model()` est indispensable pour toutes les classes AR.
La méthode retourne une instance AR qui est utilisée pour accéder aux méthodes de la classe
(de manière similaire aux méthodes des classes statiques) dans un contexte object.

Si la méthode `find` trouve une ligne satisfaisant les conditions de la requête, elle
retournera une instance de `Post` dont les propriétés contiendront les valeurs des colonnes
correspondantes de la ligne de la table. Il est alors possible de lire les valeurs chargées
de la même manière que pour un objet classique, par exemple, `echo $post->title;`.

La méthode `find` retournera null si rien n'a été trouvé en base.

Lors de l'appel à `find`, on utilise `$condition` et `$params` pour spécifier les conditions
à la requête. Ici `$condition` est une string représentant la clause `WHERE` d'une requête SQL,
et `$params` est un tableau de paramètres dont les valeurs devront être liées aux marques dans
`$condition`. Par exemple,

~~~
[php]
// trouve la ligne avec postID=10
$post=Post::model()->find('postID=:postID', array(':postID'=>10));
~~~

> Note: Dans le code ci-dessus, il est possible que vous deviez échapper la référence
à la colonne `postID` pour certain SGBD. Par exemple, si vous utilisez PostgreSQL,
vous devez écrire la condition `"postID"=:postID`, car PostgreSQL traite par défaut
les colonnes comme insensible à la casse.

Il est aussi possible d'utiliser `$condition` pour spécifier des conditions plus complexes.
A la place d'une chaîne de caractères, `$condition` pourra être une instance de [CDbCriteria],
ce qui permettra de spécifier des conditions autres que la clause `WHERE`. Par exemple,

~~~
[php]
$criteria=new CDbCriteria;
$criteria->select='titre';  // sélectionne seulement la colonne 'title'
$criteria->condition='postID=:postID';
$criteria->params=array(':postID'=>10);
$post=Post::model()->find($criteria); // $params n'est pas nécessaire
~~~

Notez que quand [CDbCriteria] est utilisé dans une condition de requête, le
paramètre `$params` n'est plus requis puisqu'il peut être spécifié dans [CDbCriteria],
comme on peut le voir ci-dessus.

Une autre méthode que l'utilisation de [CDbCriteria] est le passage d'un tableau
à la méthode `find`.
Les clés et valeurs du tableau correspondent alors respectivement aux noms et valeurs
des critères. Ainsi l'exemple ci-dessus peut être réécrit comme suit:

~~~
[php]
$post=Post::model()->find(array(
	'select'=>'titre',
	'condition'=>'postID=:postID',
	'params'=>array(':postID'=>10),
));
~~~

> Info: Quand une condition a pour but de faire correspondre des colonnes avec
des valeurs, il est possible d'utiliser [findByAttributes()|CActiveRecord::findByAttributes].
Le paramètre `$attributes` est alors un tableau de valeurs avec pour clés les noms des colonnes.
Dans certains frameworks, cette tâche est accomplie en appelant des méthodes telles que `findByNameAndTitle`.
Bien que cette approche semble intéressante, elle sème souvent la confusion, et fait apparaître
des conflits et problèmes comme la sensibilité à la casse des noms de colonnes.

Quand plusieurs lignes de données correspondent à la condition spécifiée dans la requête, il est
possible de toutes les récupérer en une seule opération en utilisant les méthodes `findAll` ci-dessous, chacune d'entres elles possédant sa méthode équivalente `find`, telles que décrites précédemment.

~~~
[php]
// trouve toutes les lignes satisfaisant la condition spécifiée
$posts=Post::model()->findAll($condition,$params);
// trouve toutes les lignes possédant les clés primaires spécifiées
$posts=Post::model()->findAllByPk($postIDs,$condition,$params);
// trouve toutes les lignes possédant les valeurs des attributs spécifiés
$posts=Post::model()->findAllByAttributes($attributes,$condition,$params);
// trouve toutes les lignes en utilisant la requête SQL spécifiée
$posts=Post::model()->findAllBySql($sql,$params);
~~~

Si aucun enregistrement ne correspond à la condition de la requête, `findAll`
retournera un tableau vide. Ce comportement est différent en cela de `find` qui
retournera null si aucun enregistrement ne correspond.

En plus des méthodes `find` et `findAll` décrites ci-dessus, les méthodes suivantes
sont aussi disponibles:

~~~
[php]
// retourne le nombre d'enregistrements correspondant à la condition
$n=Post::model()->count($condition,$params);
// retourne le nombre d'enregistrements de la requête SQL spécifiée
$n=Post::model()->countBySql($sql,$params);
// regarde s'il y a au moins un enregistrement satisfaisant la condition spécifiée
$exists=Post::model()->exists($condition,$params);
~~~

Mise à jour d'un enregistrement
-------------------------------

Une fois qu'une instance AR contient les valeurs des colonnes, il est possible de les
changer et de les sauvegarder dans la table.

~~~
[php]
$post=Post::model()->findByPk(10);
$post->title='nouveau titre du post';
$post->save(); // enregistrement dans la base
~~~

Comme l'on peut le voir, la même méthode [save()|CActiveRecord::save] est utilisée
pour les opérations d'insertion et de mise à jour. Si une instance AR est créée
en utilisant l'opérateur `new`, l'appel à [save()|CActiveRecord::save] insère une
nouvelle ligne dans la table; si l'instance AR provient du résultat de méthodes telles que
`find` ou `findAll`, l'appel à [save()|CActiveRecord::save] met à jour la ligne
existante dans la table. En fait, il est possible d'utiliser [CActiveRecord::isNewRecord]
pour savoir si une instance AR existe ou non.

Il est aussi possible de mettre à jour une ou plusieurs lignes dans une table sans
les charger au préalable. AR inclut les méthodes suivantes au niveau de la classe
dans ce but:

~~~
[php]
// met à jour les lignes correspondant à la condition spécifiée
Post::model()->updateAll($attributes,$condition,$params);
// met à jour les lignes correspondant à la condition et aux clés primaires spécifiées
Post::model()->updateByPk($pk,$attributes,$condition,$params);
// met à jour les colonne de comptage pour les lignes satisfaisant les conditions spécifiées
Post::model()->updateCounters($counters,$condition,$params);
~~~

Ci-dessus, `$attributes` est un tableau de valeurs de colonnes dont les clés correspondent
aux noms des colonnes; `$counters` est une tableau de valeurs incrémentales dont les clés sont
les noms des colonnes; et `$condition` et `$params` sont les mêmes que dans les sections précédentes.

Suppression des enregistrements
-------------------------------

Il est aussi possible de supprimer une ligne de données si une instance AR à été
chargée avec cette ligne.

~~~
[php]
$post=Post::model()->findByPk(10); // on suppose qu'un post avec un ID à 10 existe
$post->delete(); // supprime la ligne dans la table
~~~

Attention, après suppression, l'instance AR reste inchangée, même si la ligne correspondante
dans la table a déjà été effectivement supprimée.

Les méthodes suivantes de la classe sont incluses afin de pouvoir supprimer des lignes
sans les avoir chargées auparavant:

~~~
[php]
// supprime les lignes correspondant à la condition spécifiée
Post::model()->deleteAll($condition,$params);
// supprime les lignes correspondant à la condition et aux clés primaires spécifiées
Post::model()->deleteByPk($pk,$condition,$params);
~~~

Validation des données
----------------------

Durant une insertion ou mise à jour d'une ligne, il est souvent nécessaire
de vérifier si les valeurs des colonnes suivent bien certaines règles. C'est
particulièrement important si ces valeurs proviennent des utilisateurs finaux.
En général, il ne faut jamais faire confiance aux données provenant du côté client.

AR va effectuer cette validation de données automatiquement quand la méthode [save()|CActiveRecord::save]
est appelée. La validation se base sur les règles définies dans la méthodes [rules()|CModel::rules]
de la classe AR. Pour plus de détails sur comment écrire ces règles de validation, veuillez consulter
la section [Declaration des règles de validation](/doc/guide/form.model#declaring-validation-rules).
Voici ci-dessous le déroulement typique lors de l'enregistrement d'une ligne:

~~~
[php]
if($post->save())
{
	// données valides et insertion/mise à jour sans erreur
}
else
{
	// données invalides. Un appel à getErrors() retournera les messages d'erreur
}
~~~

Quand les données à insérer ou mettre à jour sont fournies par les utilisateurs finaux
sous forme HTML, il faut les assigner aux propriétés correspondantes de l'AR. Voici comment
il est possible de faire cela:

~~~
[php]
$post->title=$_POST['title'];
$post->content=$_POST['content'];
$post->save();
~~~

S'il y avait de nombreuses colonnes, il faudrait faire de nombreuses assignations.
Cela peut être évité en utilisant la propriété [attributes|CActiveRecord::attributes]
comme montré ci-dessous. Plus de détails sont disponibles dans les sections
[Securing Attribute Assignments](/doc/guide/form.model#securing-attribute-assignments)
et [Creating Action](/doc/guide/form.action).

~~~
[php]
// on suppose que $_POST['Post'] est un tableau de valeurs
// dont les clés sont les noms de colonnes
$post->attributes=$_POST['Post'];
$post->save();
~~~


Comparaison d'enregistrements
-----------------------------

Tout comme les enregistrements d'une table, les instances AR sont identifiées
de manière unique grâce à la valeur de leur clé primaire. Ainsi, afin de comparer
deux instances AR, il suffit de comparer leur clé primaire. Cependant une façon plus
simple est d'appeler la méthode [CActiveRecord::equals()].

> Info: A la différence des implémentations de AR dans les autres frameworks, Yii supporte
les clés primaires composites dans les AR. Une clé composite est consistuée de deux colonnes
ou plus. Dans ce cas, la valeur de la clé primaire est représentée dans Yii comme un tableau.
La propriété [primaryKey|CActiveRecord::primaryKey] renvoie la valeur de la clé primaire
dans une instance AR.

Cas spécifiques
---------------

[CActiveRecord] fourni des méthodes qu'il est possible de surcharger pour modifier le
comportement de la classe.

   - [beforeValidate|CModel::beforeValidate] et
[afterValidate|CModel::afterValidate]: invoquées avant et après la validation.

   - [beforeSave|CActiveRecord::beforeSave] and
[afterSave|CActiveRecord::afterSave]: invoquées avant et après l'enregistrement d'une instance AR.

   - [beforeDelete|CActiveRecord::beforeDelete] and
[afterDelete|CActiveRecord::afterDelete]: invoquées avant et après la suppression d'une instance AR.

   - [afterConstruct|CActiveRecord::afterConstruct]: invoquée pour chaque instance AR créée avec
l'opérateur `new`.

   - [beforeFind|CActiveRecord::beforeFind]: invoquée avant que le AR finder
exécute une requête (par exemple `find()`, `findAll()`). Disponible depuis la version 1.0.9.

   - [afterFind|CActiveRecord::afterFind]: invoquée après chaque création d'instance AR
issue du résultat d'une requête.


Utilisation des transactions avec AR
------------------------------------

Chaque instance AR contient une propriété nommée
[dbConnection|CActiveRecord::dbConnection] qui est une instance de [CDbConnection].
Il est donc possible d'utiliser la fonctionnalité de [transaction](/doc/guide/database.dao#using-transactions)
fourni par Yii DAO si besoin:

~~~
[php]
$model=Post::model();
$transaction=$model->dbConnection->beginTransaction();
try
{
	// find et sqve sont des actions qui peuvent se produirent dans une autre requête
	// il faut donc utiliser une transaction pour garantir l'intégrité des données
	$post=$model->findByPk(10);
	$post->title='new post title';
	$post->save();
	$transaction->commit();
}
catch(Exception $e)
{
	$transaction->rollBack();
}
~~~


Named Scopes
------------

> Note: Le support pour les named scopes est disponible depuis la version 1.0.5.
> L'idée originelle des named scopes provient de Ruby on Rails.

Un *named scope* représente un critère *named* d'une requête qui peut être combiné avec
d'autres named scopes et appliqués ensemble dans une requête sur un active record.

Les Named scopes sont normalement déclarés dans la méthode [CActiveRecord::scopes()] comme des paires de noms-critères. Le code suivant déclare deux named scopes, `published` et `recently`, dans la classe modélisant `Post`:

~~~
[php]
class Post extends CActiveRecord
{
	......
	public function scopes()
	{
		return array(
			'published'=>array(
				'condition'=>'status=1',
			),
			'recently'=>array(
				'order'=>'create_time DESC',
				'limit'=>5,
			),
		);
	}
}
~~~

Chaque named scope est déclaré comme un tableau qui est utilisé pour initialiser une instance [CDbCriteria]. Par exemple, le named scope `recently` indique que la propriété `order` sera `create_time DESC` et que la propriété `limit` sera 5, ce qui donne un critère de requête qui retournera les 5 posts les plus récents.

Les Named scopes vont principalement être utilisés pour altérer les appels aux méthodes `find`. Plusieurs named scopes peuvent être chainés ensemble pour restreindre les résultats de la requête. Par exemple, pour trouver les posts récemment publiés, il est possible de faire:

~~~
[php]
$posts=Post::model()->published()->recently()->findAll();
~~~

En général, les named scopes doivent se situer à gauche de l'appel à la méthode `find`. Chacun fournit un critère pour la requête, qui sera combiné avec les autres critères, dont celui passé en paramètre de la méthode `find`. Finalement cela revient à ajouter une liste de filtre à la requête.

A partir de la version 1.0.6, les named scopes peuvent aussi être utilisés avec les méthodes `update` et `delete`. Par exemple, le code suivant supprime tous les posts récemment publiés:

~~~
[php]
Post::model()->published()->recently()->delete();
~~~

> Note: Les Named scopes peuvent seulement être utilisé avec les méthodes du niveau de la classe. Ainsi la méthode doit être appelée en utilisant `ClassName::model()`.


### Named Scopes avec paramètres

Les Named scopes sont paramètrables. Par exemple, nous pourrions avoir besoin de configurer le nombre de posts indiqué dans le named scope `recently`. Pour cela, au lieu de déclarer le named scope dans la méthode [CActiveRecord::scopes], il faut le faire dans une nouvelle méthode dont le nom est le même que celui du named scope:

~~~
[php]
public function recently($limit=5)
{
	$this->getDbCriteria()->mergeWith(array(
		'order'=>'create_time DESC',
		'limit'=>$limit,
	));
	return $this;
}
~~~

Il est alors possible d'utiliser le code ci-dessous pour récupérer les 3 posts récemment publiés:

~~~
[php]
$posts=Post::model()->published()->recently(3)->findAll();
~~~

Si le paramètre 3 ci-dessus n'est pas spécifié, les 5 derniers posts publiés sont renvoyés par défaut.


### Scope par défaut

Une classe peut avoir un named scope par défaut qui peut être appliqué à toutes les requêtes (dont les relationelles) sur un modèle. Par exemple, un site web supportant plusieurs langues souhaite afficher uniquement le contenu correspondant à la langue définie par l'utilisateur. Comme il se peut qu'il y ait beaucoup de requêtes concernant le contenu du site, il est possible de définir un named scope par défaut pour régler ce problème. Pour cela, il faut surcharger la méthode [CActiveRecord::defaultScope] comme ci-dessous:

~~~
[php]
class Content extends CActiveRecord
{
	public function defaultScope()
	{
		return array(
			'condition'=>"language='".Yii::app()->language."'",
		);
	}
}
~~~

Tous les appels aux méthodes find utiliseront alors automatiquement le critère défini ci-dessus.

~~~
[php]
$contents=Content::model()->findAll();
~~~

> Note: Le scope par défaut et les scopes nommés ne s'appliquent que sur les requêtes `SELECT`. Ils sont ignorés pour les requêtes `INSERT`, `UPDATE` et `DELETE`.

<div class="revision">$Id: database.ar.txt 1682 2013-11-20$</div>
